/**********************************************************************

Audacity: A Digital Audio Editor

ProjectAudioIO.cpp

Paul Licameli split from AudacityProject.cpp

**********************************************************************/

#include "ProjectAudioIO.h"

#include "AudioIOBase.h"
#include "Mix.h"
#include "Project.h"
#include "ProjectRate.h"

AudioIOStartStreamOptions
ProjectAudioIO::DefaultOptionsFactory(AudacityProject& project, bool)
{
    auto& projectAudioIO = Get(project);
    AudioIOStartStreamOptions options{
        project.shared_from_this(), ProjectRate::Get(project).GetRate()
    };
    options.captureMeter = projectAudioIO.GetCaptureMeter();
    options.playbackMeter = projectAudioIO.GetPlaybackMeter();
    options.envelope
        =Mixer::WarpOptions::DefaultWarp::Call(&project);
    // options.listener remains null
    // boolean argument is ignored
    return options;
}

AudioIOStartStreamOptions ProjectAudioIO::GetDefaultOptions(
    AudacityProject& project, bool newDefaults)
{
    return DefaultOptions::Call(project, newDefaults);
}

static const AudacityProject::AttachedObjects::RegisteredFactory sAudioIOKey{
    []( AudacityProject& parent ){
        return std::make_shared< ProjectAudioIO >(parent);
    }
};

ProjectAudioIO& ProjectAudioIO::Get(AudacityProject& project)
{
    return project.AttachedObjects::Get< ProjectAudioIO >(sAudioIOKey);
}

const ProjectAudioIO& ProjectAudioIO::Get(const AudacityProject& project)
{
    return Get(const_cast<AudacityProject&>(project));
}

ProjectAudioIO::ProjectAudioIO(AudacityProject& project)
    : mProject{project}
{
}

ProjectAudioIO::~ProjectAudioIO()
{
}

int ProjectAudioIO::GetAudioIOToken() const
{
    return mAudioIOToken;
}

void ProjectAudioIO::SetAudioIOToken(int token)
{
    mAudioIOToken = token;
}

bool ProjectAudioIO::IsAudioActive() const
{
    auto gAudioIO = AudioIOBase::Get();
    return GetAudioIOToken() > 0
           && gAudioIO->IsStreamActive(GetAudioIOToken());
}

const std::shared_ptr<IMeterSender>& ProjectAudioIO::GetPlaybackMeter() const
{
    return mPlaybackMeter;
}

void ProjectAudioIO::SetPlaybackMeter(
    const std::shared_ptr<IMeterSender>& playback)
{
    auto& project = mProject;
    mPlaybackMeter = playback;
    auto gAudioIO = AudioIOBase::Get();
    if (gAudioIO) {
        gAudioIO->SetPlaybackMeter(project.shared_from_this(), mPlaybackMeter);
    }
}

const std::shared_ptr<IMeterSender>& ProjectAudioIO::GetCaptureMeter() const
{
    return mCaptureMeter;
}

void ProjectAudioIO::SetCaptureMeter(
    const std::shared_ptr<IMeterSender>& capture)
{
    auto& project = mProject;
    mCaptureMeter = capture;

    auto gAudioIO = AudioIOBase::Get();
    if (gAudioIO) {
        gAudioIO->SetCaptureMeter(project.shared_from_this(), mCaptureMeter);
    }
}

void ProjectAudioIO::SetPlaySpeed(double value)
{
    if (auto oldValue = GetPlaySpeed(); value != oldValue) {
        mPlaySpeed.store(value, std::memory_order_relaxed);
        Publish({});
    }
}
